package com.haojiang.mh.widget.chart;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.*;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import androidx.annotation.Nullable;
import com.haojiang.mh.R;
import com.haojiang.mh.service.entity.MinMaxBean;
import com.haojiang.mh.service.entity.MinMaxChartBean;
import com.haojiang.mh.service.entity.TwoValueChartBean;
import com.haojiang.mh.utils.MUtil;
import com.haojiang.mh.utils.SizeUtil;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 两层：背景（渐变+横线格）+柱子（圆角渐变柱、双矩形柱）
 * 现用在《月报心率、呼吸、体动、录音》
 */
public class MonthSignChartView extends View {

    public static final int ROUND_RECT = 0;
    public static final int TWO_COLUMN = 1;

    private TextPaint textPaint;//文字画笔
    //背景、线条、柱子、坐标 画笔
    private Paint bgPaint, linePaint, columnPaint, coordinatePaint;
    //Y轴开始点值、Y轴间隔大小、Y轴坐标个数（去除起点个数）
    private int yStartCoordinate, yIntervalLocal, yInterval, yCoordinateNum, yMaxCoordinate;
    private int width, height, defaultWidth, defaultHeight;//当前View宽高、默认宽高
    private float xItemWidth, yItemHeight;//X轴间隔块宽度、Y轴间隔块高度
    private int xCoordinateNum, xAxisPadding;//X轴坐标个数、X轴左右间距
    private int commonColor, sundayColor, lineColor;//通用、周日、线条 颜色值
    private int bottomY, columnWidth, drawHeight, twoColumnGap;//DOUBLE类型下两柱子之间间隔
    private int xAxisHeight, xAxisTextHeight;//X轴高度、X轴文本高度
    private int yAxisWidth, yAxisTextHeight;//Y轴宽度、Y轴文字高度
    private int paddingTop;//View顶部间距
    private int bgGraTopColor, bgGraBottomColor;//背景渐变顶部、底部色值
    private int columnGraTopColor, columnGraBottomColor;//柱子渐变顶部、底部色值
    private int leftColumnColor, rightColumnColor;//左边、右边柱子色值
    private LinearGradient shader;//颜色线性渐变
    private RectF rectF = new RectF();//矩形
    private int xAxisTextSize, yAxisTextSize;//X轴文字、Y轴文字大小
    private int chartType;//图表类型 ROUND、DOUBLE
    private List<MinMaxChartBean> roundRectList;//圆角矩形数据集
    private List<TwoValueChartBean> twoColumnList;//双柱数据集

    public MonthSignChartView(Context context) {
        this(context, null);
    }

    public MonthSignChartView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MonthSignChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        @SuppressLint("CustomViewStyleable")
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ChartModuleAttribute, defStyleAttr, 0);
        yStartCoordinate = a.getInt(R.styleable.ChartModuleAttribute_cm_y_start, 0);
        yIntervalLocal = a.getInt(R.styleable.ChartModuleAttribute_cm_y_interval, 5);
        yCoordinateNum = a.getInt(R.styleable.ChartModuleAttribute_cm_y_number, 8);
        chartType = a.getInt(R.styleable.ChartModuleAttribute_cm_chart_type, ROUND_RECT);
        yInterval = yIntervalLocal;
        a.recycle();

        initView(context);
    }

    private void initView(Context context) {

        xAxisHeight = SizeUtil.dp2px(context, 3);
        xAxisTextHeight = SizeUtil.dp2px(context, 30);
        yAxisWidth = SizeUtil.dp2px(context, 30);
        yAxisTextHeight = SizeUtil.dp2px(context, 20);
        drawHeight = SizeUtil.dp2px(context, 130);
        paddingTop = SizeUtil.dp2px(context, 10);
        xAxisPadding = SizeUtil.dp2px(context, 10);
        columnWidth = SizeUtil.dp2px(context, 2);
        twoColumnGap = SizeUtil.dp2px(context, 1);

        defaultWidth = SizeUtil.dp2px(context, 340);
        defaultHeight = paddingTop + drawHeight + xAxisHeight + xAxisTextHeight;

        commonColor = getResources().getColor(R.color.white_half);
        sundayColor = getResources().getColor(R.color.purple_3);
        lineColor = getResources().getColor(R.color.white) & 0x19FFFFFF;
        columnGraTopColor = getResources().getColor(R.color.purple_3);
        columnGraBottomColor = getResources().getColor(R.color.purple_4);
        bgGraTopColor = getResources().getColor(R.color.white) & 0x00FFFFFF;
        bgGraBottomColor = getResources().getColor(R.color.white) & 0x19FFFFFF;
        leftColumnColor = getResources().getColor(R.color.purple_3);
        rightColumnColor = getResources().getColor(R.color.purple_4);

        xAxisTextSize = SizeUtil.sp2px(context, 12);
        yAxisTextSize = SizeUtil.sp2px(context, 10);

        textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setTextAlign(Paint.Align.CENTER);

        coordinatePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        coordinatePaint.setStyle(Paint.Style.FILL);
        coordinatePaint.setColor(commonColor);

        columnPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        columnPaint.setStyle(Paint.Style.FILL);

        linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        linePaint.setColor(lineColor);
        linePaint.setStrokeWidth(2);

        bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bgPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = w;
        height = h;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (chartType == ROUND_RECT) {
            if (roundRectList == null || roundRectList.isEmpty()) return;
            xCoordinateNum = roundRectList.size();
        } else {
            if (twoColumnList == null || twoColumnList.isEmpty()) return;
            xCoordinateNum = twoColumnList.size();
        }

        xItemWidth = (float) (width - xAxisPadding * 2 - yAxisWidth) / (xCoordinateNum - 1);
        yItemHeight = (float) drawHeight / yCoordinateNum;
        bottomY = paddingTop + drawHeight;
        yMaxCoordinate = yStartCoordinate + yCoordinateNum * yInterval;

        drawXAxis(canvas);

        drawYAxis(canvas);

        drawBackGround(canvas);

        if (chartType == ROUND_RECT) {
            drawRoundRect(canvas);
        } else {
            drawTwoColumn(canvas);
        }
    }

    /**
     * 绘制X轴
     */
    private void drawXAxis(Canvas canvas) {
        String dayText;
        textPaint.setTextSize(xAxisTextSize);
        for (int i = 0; i < xCoordinateNum; i++) {
            if (i % 7 != 0) continue;
            if (chartType == ROUND_RECT) {
                dayText = roundRectList.get(i).getDay();
                textPaint.setColor(roundRectList.get(i).isCurrMonth() ? sundayColor : commonColor);
            } else {
                dayText = twoColumnList.get(i).getDay();
                textPaint.setColor(twoColumnList.get(i).isCurrMonth() ? sundayColor : commonColor);
            }
            canvas.drawLine(
                    xAxisPadding + xItemWidth * i,
                    bottomY,
                    xAxisPadding + xItemWidth * i,
                    bottomY + xAxisHeight,
                    coordinatePaint
            );
            canvas.drawText(
                    dayText,
                    xAxisPadding + xItemWidth * i,
                    SizeUtil.getBaseLine(textPaint, height, xAxisTextHeight),
                    textPaint
            );
        }
    }

    /**
     * 绘制Y轴
     */
    private void drawYAxis(Canvas canvas) {
        textPaint.setColor(commonColor);
        textPaint.setTextSize(yAxisTextSize);
        for (int i = 1; i <= yCoordinateNum; i++) {
            canvas.drawText(
                    String.valueOf(yStartCoordinate + i * yInterval),
                    width - yAxisWidth * 0.5f,
                    SizeUtil.getBaseLine(textPaint, bottomY - yItemHeight * i + yAxisTextHeight * 0.5f, yAxisTextHeight),
                    textPaint
            );
        }
    }

    /**
     * 绘制背景
     */
    private void drawBackGround(Canvas canvas) {
        shader = new LinearGradient(0, paddingTop, 0, bottomY, bgGraTopColor, bgGraBottomColor, Shader.TileMode.CLAMP);
        int weekNum = (xCoordinateNum - 1) / 7;
        bgPaint.setShader(shader);
        for (int i = 0; i < weekNum; i++) {//渐变背景
            if (i % 2 != 0) continue;
            float left = xAxisPadding + xItemWidth * 7 * i;
            float right = left + xItemWidth * 7;
            canvas.drawRect(left, paddingTop, right, bottomY, bgPaint);
        }
        //横线格
        for (int i = 0; i <= yCoordinateNum; i++) {
            canvas.drawLine(
                    0,
                    bottomY - yItemHeight * i,
                    width - yAxisWidth,
                    bottomY - yItemHeight * i,
                    linePaint
            );
        }
    }

    /**
     * 绘制圆角矩形
     */
    private void drawRoundRect(Canvas canvas) {
        for (int i = 0; i < roundRectList.size(); i++) {
            MinMaxChartBean bean = roundRectList.get(i);
            if (bean == null || bean.getLine() == null || bean.getLine().isNull()) continue;
            MinMaxBean mmb = bean.getLine();
            if (mmb.getMax() == mmb.getMin()) continue;
            if (mmb.getMax() <= yStartCoordinate || mmb.getMin() >= yMaxCoordinate) continue;
            if (mmb.getMin() < yStartCoordinate) mmb.setMin(yStartCoordinate);
            if (mmb.getMax() > yMaxCoordinate) mmb.setMax(yMaxCoordinate);
            float left = xAxisPadding + xItemWidth * i - columnWidth * 0.5f;
            float top = paddingTop + (yMaxCoordinate - mmb.getMax()) * drawHeight * 1.0f / (yMaxCoordinate - yStartCoordinate);
            float right = xAxisPadding + xItemWidth * i + columnWidth * 0.5f;
            float bottom = paddingTop + (yMaxCoordinate - mmb.getMin()) * drawHeight * 1.0f / (yMaxCoordinate - yStartCoordinate);
            shader = new LinearGradient(0, top, 0, bottom, columnGraTopColor, columnGraBottomColor, Shader.TileMode.CLAMP);
            columnPaint.setShader(shader);
            rectF.set(left, top, right, bottom);
            canvas.drawRoundRect(rectF, columnWidth * 0.5f, columnWidth * 0.5f, columnPaint);
        }
    }

    /**
     * 绘制双柱
     */
    private void drawTwoColumn(Canvas canvas) {
        columnPaint.setShader(null);
        for (int i = 0; i < twoColumnList.size(); i++) {
            TwoValueChartBean bean = twoColumnList.get(i);
            if (bean == null || bean.isNull()) continue;
            if (bean.getLeftValue() <= yStartCoordinate) continue;
            if (bean.getRightValue() <= yStartCoordinate) continue;
            if (bean.getLeftValue() > yMaxCoordinate) bean.setLeftValue(yMaxCoordinate);
            if (bean.getRightValue() > yMaxCoordinate) bean.setRightValue(yMaxCoordinate);
            float xMidPosition = xAxisPadding + xItemWidth * i;
            rectF.set(
                    xMidPosition - twoColumnGap * 0.5f - columnWidth,
                    paddingTop + (yMaxCoordinate - bean.getLeftValue()) * drawHeight * 1.0f / (yMaxCoordinate - yStartCoordinate),
                    xMidPosition - twoColumnGap * 0.5f,
                    bottomY
            );
            columnPaint.setColor(leftColumnColor);
            canvas.drawRect(rectF, columnPaint);
            rectF.set(
                    xMidPosition + twoColumnGap * 0.5f,
                    paddingTop + (yMaxCoordinate - bean.getRightValue()) * drawHeight * 1.0f / (yMaxCoordinate - yStartCoordinate),
                    xMidPosition + twoColumnGap * 0.5f + columnWidth,
                    bottomY
            );
            columnPaint.setColor(rightColumnColor);
            canvas.drawRect(rectF, columnPaint);
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(
                getMeasuredLength(widthMeasureSpec, true),
                getMeasuredLength(heightMeasureSpec, false)
        );
    }

    private int getMeasuredLength(int length, boolean isWidth) {
        int specMode = MeasureSpec.getMode(length);
        int specSize = MeasureSpec.getSize(length);
        int size;
        int padding = isWidth ? getPaddingLeft() + getPaddingRight() : getPaddingTop() + getPaddingBottom();
        if (specMode == MeasureSpec.EXACTLY) {
            size = specSize;
        } else if (specMode == MeasureSpec.UNSPECIFIED) {
            size = isWidth ? defaultWidth : defaultHeight;
        } else {
            size = isWidth ? padding + defaultWidth : padding + defaultHeight;
            if (specMode == MeasureSpec.AT_MOST) {
                size = Math.min(size, specSize);
            }
        }
        return size;
    }

    /**
     * 更新圆角柱状图数据集
     */
    public void setRoundRectData(List<MinMaxChartBean> data) {
        this.chartType = ROUND_RECT;
        if (roundRectList == null) roundRectList = new ArrayList<>();
        roundRectList.clear();
        if (data != null && !data.isEmpty()) {
            roundRectList.addAll(data);
            int localSet = yStartCoordinate + yIntervalLocal * yCoordinateNum;
            int max = 0;
            for (int i = 0; i < roundRectList.size(); i++) {
                MinMaxChartBean bean = roundRectList.get(i);
                max = Math.max(bean.getLine().getMax(), max);
            }
            int finalMax = Math.max(max, localSet);
            double ceil = Math.ceil(finalMax * 1.0f / localSet);
            yInterval = (int) (localSet * ceil / yCoordinateNum);
            getCompleteMonthData();
        }
        invalidate();
    }

    /**
     * 更新双柱状图数据集
     */
    public void setTwoColumnData(List<TwoValueChartBean> data) {
        this.chartType = TWO_COLUMN;
        if (twoColumnList == null) twoColumnList = new ArrayList<>();
        twoColumnList.clear();
        if (data != null && !data.isEmpty()) {
            twoColumnList.addAll(data);
            int localSet = yStartCoordinate + yIntervalLocal * yCoordinateNum;
            int max = 0;
            for (int i = 0; i < twoColumnList.size(); i++) {
                TwoValueChartBean bean = twoColumnList.get(i);
                int maxNum = Math.max(bean.getLeftValue(), bean.getRightValue());
                max = Math.max(maxNum, max);
            }
            int finalMax = Math.max(max, localSet);
            double ceil = Math.ceil(finalMax * 1.0f / localSet);
            yInterval = (int) (localSet * ceil / yCoordinateNum);
            getCompleteMonthData();
        }
        invalidate();
    }

    /**
     * 获取完整月份（包含前后月的周末）数据
     */
    private void getCompleteMonthData() {
        int[] ymd;
        if (chartType == ROUND_RECT) {
            ymd = MUtil.INSTANCE.getYearMonthDay(roundRectList.get(0).getDate());
        } else {
            ymd = MUtil.INSTANCE.getYearMonthDay(twoColumnList.get(0).getDate());
        }
        Calendar cal = Calendar.getInstance();
        cal.set(ymd[0], ymd[1] - 1, ymd[2]);

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
        while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
            addBeanList(simpleDateFormat.format(new Date(cal.getTimeInMillis())), true);
        }
        cal.set(ymd[0], ymd[1], ymd[2]);
        while (cal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {
            addBeanList(simpleDateFormat.format(new Date(cal.getTimeInMillis())), false);
            cal.add(Calendar.DAY_OF_MONTH, 1);
        }
        addBeanList(simpleDateFormat.format(new Date(cal.getTimeInMillis())), false);
    }

    /**
     * 添加Bean
     */
    private void addBeanList(String date, boolean isBefore) {
        if (chartType == ROUND_RECT) {
            MinMaxChartBean bean = new MinMaxChartBean();
            bean.setDate(date);
            bean.setCurrMonth(false);
            if (isBefore) {
                roundRectList.add(0, bean);
            } else {
                roundRectList.add(bean);
            }
        } else {
            TwoValueChartBean bean = new TwoValueChartBean();
            bean.setDate(date);
            bean.setCurrMonth(false);
            if (isBefore) {
                twoColumnList.add(0, bean);
            } else {
                twoColumnList.add(bean);
            }
        }
    }
}
